package club.kynb.mall.payment.exec;

import club.kynb.mall.payment.constant.TradeOrderStatusEnum;
import club.kynb.mall.payment.dto.ext.PayRequestDTO;
import club.kynb.mall.payment.dto.ext.RefundRequestDTO;
import club.kynb.mall.payment.dto.ext.RefundResultDTO;
import club.kynb.mall.payment.dto.ext.TradeNotifyDTO;
import club.kynb.mall.payment.dto.third.PayExecutorQueryResultDTO;
import club.kynb.mall.payment.dto.third.PayExecutorResultDTO;
import club.kynb.mall.payment.mysql.po.PayTradeOrderPO;
import cn.hutool.json.JSONObject;
import cn.hutool.json.JSONUtil;
import lombok.AllArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.pizza.common.web.exception.Errors;
import org.pizza.util.Checker;

import java.math.BigDecimal;
import java.util.Date;

/**
 * @author kynb_club@163.com
 * @date: 2021/7/7
 */
@Slf4j
@AllArgsConstructor
public abstract class AbstractPayExecutor implements PayExecutorService {


    private static final String SUCCESS = "SUCCESS";



    @Override
    public PayExecutorResultDTO createPay(PayRequestDTO dto, PayTradeOrderPO tradeOrder) {
        PayExecutorResultDTO resultDTO = new PayExecutorResultDTO();
        resultDTO.setPayAmount(tradeOrder.getPayAmount());
        JSONObject data = null;
        try {
            data = doCreatePay();
            resultDTO.setPayFlowNo(data.getStr("flowNo"));
            resultDTO.setParams(JSONUtil.toJsonStr(dto));
            resultDTO.setPayData(data.getStr("payData"));
            resultDTO.setStatus(TradeOrderStatusEnum.WAITING_4_UPDATE);
            resultDTO.setReturnInfo(data.toString());
            return resultDTO;
        } catch (Exception e) {
            log.error("userId:{} payChannel:{}  支付请求失败:{} ",dto.getUserId(),dto.getPayChannel(),e);
            resultDTO.setParams(JSONUtil.toJsonStr(dto));
            resultDTO.setReturnInfo(data != null ? data.toString() : e.getMessage());
            resultDTO.setStatus(TradeOrderStatusEnum.FAILURE);
            return resultDTO;
        }
    }

    protected abstract JSONObject doCreatePay();


    @Override
    public PayExecutorQueryResultDTO query( PayTradeOrderPO tradeOrder){
        JSONObject data = null;
        try {
            data = doQuery(tradeOrder);
            Checker.ifNullThrow(data,()->Errors.BIZ.exception("支付结果获取失败"));
            String status = data.getStr("status");
            if("1".equals(status)){
                return new PayExecutorQueryResultDTO()
                        .setStatus(TradeOrderStatusEnum.SUCCESS)
                        .setPayAmount(new BigDecimal(data.getStr("amt")))
                        .setReturnInfo(data.toString())
                        .setPayTime(new Date());
            }else if("0".equals(status)){
                return new PayExecutorQueryResultDTO()
                        .setStatus(TradeOrderStatusEnum.WAITING_4_UPDATE)
                        .setReturnInfo(data.toString());
            }else {
                return new PayExecutorQueryResultDTO()
                        .setStatus(TradeOrderStatusEnum.FAILURE)
                        .setReturnInfo(data.toString());
            }
        } catch (Exception e) {
            log.error("tradeOrderNo:{} 支付结果获取失败:{} ",tradeOrder.getTradeOrderNo(),e);
            return new PayExecutorQueryResultDTO()
                    .setStatus(TradeOrderStatusEnum.WAITING_4_UPDATE)
                    .setReturnInfo(data != null ? data.toString() : null);
        }
    }

    protected abstract JSONObject doQuery(PayTradeOrderPO tradeOrder);

    @Override
    public RefundResultDTO refund(RefundRequestDTO dto) {
        return null;
    }

    @Override
    public void notify(TradeNotifyDTO dto) {

    }





}
